<!--
 * @Author: aster lipian1004@163.com
 * @Date: 2025-02-20 17:09:13
 * @FilePath: \aster-flowable-uniapp\src\components\form\render\date-time.vue
 * @Description: 日期
 * Copyright (c) 2025 by Aster, All Rights Reserved.
-->
<template>
  <van-field
    v-if="!_hidden"
    v-model="_value"
    :name="formItemProp"
    :readonly="true"
    :required="_required"
    :rules="_rules"
    :input-align="FieldInputAlignEnum.RIGHT"
    :error-message-align="FieldInputAlignEnum.RIGHT"
    :label-width="showLabel ? '' : '5rpx'"
    is-link
    :placeholder="_placeholder"
    @click="handleOpen"
  >
    <template #label>
      <text v-if="showLabel">{{ formItem.title }}</text>
    </template>
  </van-field>
  <van-popup v-model:show="showPicker" round position="bottom">
    <van-picker-group
      :tabs="_tabs"
      cancel-button-text="清除"
      @confirm="handleConfirm"
      @cancel="handleCancel"
    >
      <van-date-picker
        v-if="_formatType.dateType"
        v-model="dateValue"
        :columns-type="_formatType.dateType"
      />
      <van-time-picker
        v-if="_formatType.timeType"
        v-model="timeValue"
        :columns-type="_formatType.timeType"
      />
    </van-picker-group>
  </van-popup>
</template>
<script setup lang="ts">
  import { evaluateFormula, getDateTypeByFormat } from '@/utils/workflow';
  import { computed, PropType, ref, watch } from 'vue';
  import { isNotEmpty } from '@/utils/is';
  import { instanceInfoByCustomParamsApi } from '@/api/workflow/process';
  import { FormPermissionEnum } from '@/enums/workFlowEnum';
  import { FieldInputAlignEnum } from '@/enums/formEnum';
  import { onLoad } from '@dcloudio/uni-app';

  const emit = defineEmits(['update:value']);
  const props = defineProps({
    value: {
      type: String,
      default: '',
    },
    mode: {
      type: String as PropType<'design' | 'form' | 'search' | 'table' | 'print'>,
      default: 'design',
    },
    formData: {
      type: Object as PropType<WorkForm.FormDataModel>,
      default: {},
    },
    formItem: {
      type: Object as PropType<WorkComponent.ComponentConfig>,
      default: {},
    },
    tableId: {
      type: String,
      default: '',
    },
    tableIndex: {
      type: Number,
      default: 0,
    },
    showLabel: {
      type: Boolean,
      default: true,
    },
  });

  // 显示弹出层
  const showPicker = ref(false);
  // 日期值
  const dateValue = ref<string[]>([]);
  // 时间值
  const timeValue = ref<string[]>([]);

  // 打开弹出层
  const handleOpen = () => {
    if (!_readonly.value) {
      showPicker.value = true;
    }
  };

  // 确认选择
  const handleConfirm = () => {
    if (_formatType.value.timeType) {
      _value.value = dateValue.value.join('-') + ' ' + timeValue.value.join(':');
    } else {
      _value.value = dateValue.value.join('-');
    }
    showPicker.value = false;
  };

  // 取消选择
  const handleCancel = () => {
    dateValue.value = [];
    timeValue.value = [];
    _value.value = '';
    showPicker.value = false;
  };

  // 键
  const formItemProp = computed(() => {
    if (isNotEmpty(props.tableId)) {
      return props.tableId + '.' + props.tableIndex + '.' + props.formItem.id;
    } else {
      return props.formItem.id;
    }
  });

  /**
   * @description: 日期时间类型
   */
  const _formatType = computed(() => {
    return getDateTypeByFormat(props.formItem.props.format);
  });

  /**
   * @description: 页签
   */
  const _tabs = computed(() => {
    let tabs: string[] = [];
    if (_formatType.value && _formatType.value.dateType) {
      tabs.push('选择日期');
    }
    if (_formatType.value && _formatType.value.timeType) {
      tabs.push('选择时间');
    }
    return tabs;
  });

  /**
   * @description: 组件值
   */
  const _value = computed({
    get() {
      return props.value;
    },
    set(val) {
      emit('update:value', val);
    },
  });

  /**
   * @description: 是否隐藏, true-隐藏
   */
  const _hidden = computed(() => {
    let r = false;
    // 解析隐藏条件公式
    if (props.formItem.props.hidden) {
      let expression = props.formItem.props.hidden;
      // 如果是子表中的控件，则需要用到下标
      if (isNotEmpty(props.tableId)) {
        expression = expression.replaceAll('?', props.tableIndex);
      }
      r = evaluateFormula(expression, props.formData);
    }
    // 判断流程节点下该控件是否隐藏
    if (props.formItem.operation && props.formItem.operation.length > 0) {
      r = r || props.formItem.operation[0] == FormPermissionEnum.HIDDEN;
    }
    return r;
  });

  /**
   * @description: 提示词
   */
  const _placeholder = computed(() => {
    if (_readonly.value) {
      return '';
    }
    return isNotEmpty(_value.value) ? '' : '请选择';
  });

  /**
   * @description: 是否必填, true-必填
   */
  const _required = computed(() => {
    return props.formItem.props.required;
  });

  /**
   * @description: 校验规则
   */
  const _rules = computed(() => {
    const isRequired = _required.value;
    if (props.mode != 'form') {
      return [];
    }
    return isRequired ? [{ required: true, message: `请选择${props.formItem.title}` }] : [];
  });

  /**
   * @description: 是否只读, true-只读
   */
  const _readonly = computed(() => {
    let r = props.formItem.props.readonly;
    if (props.formItem.operation && props.formItem.operation.length > 0) {
      r = r || props.formItem.operation[0] == FormPermissionEnum.READONLY;
    }
    return r;
  });

  /**
   * @description: 监听表单数据变化
   */
  const _formData = computed(() => {
    return JSON.parse(JSON.stringify(props.formData));
  });

  /**
   * @description: 监听表单数据变化
   */
  watch(
    () => _formData.value,
    async (nval, oval) => {
      if (nval && props.mode === 'form' && props.formItem && props.formItem.props.default) {
        // 默认值-计算公式
        const defaultConfig = props.formItem.props.default;
        if (defaultConfig.type === 'formula' && isNotEmpty(defaultConfig.value)) {
          Object.keys(nval).forEach((key) => {
            if (
              defaultConfig.value.indexOf(key) != -1 &&
              oval != undefined &&
              nval[key] != oval[key]
            ) {
              _value.value = evaluateFormula(defaultConfig.value, nval) + '';
            }
          });
        }
        // 默认值-数据联动
        if (
          defaultConfig.type === 'linkage' &&
          isNotEmpty(defaultConfig.linkage.formCode) &&
          isNotEmpty(defaultConfig.linkage.conditions) &&
          isNotEmpty(defaultConfig.linkage.dataFill)
        ) {
          const conditionStr = JSON.stringify(defaultConfig.linkage.conditions);
          Object.keys(nval).forEach(async (key) => {
            // 判断联动条件中的当前表单的字段的值是否有变动，如有则重新赋值
            if (conditionStr.indexOf(key) != -1 && oval != undefined && nval[key] != oval[key]) {
              const targetCode = defaultConfig.linkage.formCode[1];
              let targetParams = {};
              defaultConfig.linkage.conditions.forEach((item) => {
                if (isNotEmpty(item.currentFieldId) && isNotEmpty(item.associatedFieldId)) {
                  targetParams[item.associatedFieldId] = nval[item.currentFieldId];
                }
              });
              // 根据条件查询目标表单的流程实例
              await instanceInfoByCustomParamsApi(targetCode, targetParams).then(({ data }) => {
                if (data) {
                  const dataFill = defaultConfig.linkage.dataFill;
                  // 如果目标表单中存在该填充字段，则赋值
                  if (data.hasOwnProperty(dataFill)) {
                    _value.value = data[dataFill];
                  }
                } else {
                  // 流程实例不存在则重置为空
                  _value.value = props.formItem.value;
                }
              });
            }
          });
        }
      }
    },
    { immediate: true, deep: true },
  );

  onLoad(() => {
    if (isNotEmpty(_value.value)) {
      if (_value.value.length === 4) {
        dateValue.value = [String(_value.value).substring(0, 4)];
      } else if (_value.value.length === 7) {
        dateValue.value = [
          String(_value.value).substring(0, 4),
          String(_value.value).substring(5, 7),
        ];
      } else if (_value.value.length === 10) {
        dateValue.value = [
          String(_value.value).substring(0, 4),
          String(_value.value).substring(5, 7),
          String(_value.value).substring(8, 10),
        ];
      } else if (_value.value.length === 13) {
        dateValue.value = [
          String(_value.value).substring(0, 4),
          String(_value.value).substring(5, 7),
          String(_value.value).substring(8, 10),
        ];
        timeValue.value = [String(_value.value).substring(11, 13)];
      } else if (_value.value.length === 16) {
        dateValue.value = [
          String(_value.value).substring(0, 4),
          String(_value.value).substring(5, 7),
          String(_value.value).substring(8, 10),
        ];
        timeValue.value = [
          String(_value.value).substring(11, 13),
          String(_value.value).substring(14, 16),
        ];
      } else if (_value.value.length === 19) {
        dateValue.value = [
          String(_value.value).substring(0, 4),
          String(_value.value).substring(5, 7),
          String(_value.value).substring(8, 10),
        ];
        timeValue.value = [
          String(_value.value).substring(11, 13),
          String(_value.value).substring(14, 16),
          String(_value.value).substring(17, 19),
        ];
      } else {
        dateValue.value = [];
        timeValue.value = [];
      }
    }
  });

  defineExpose({
    _hidden,
  });
</script>
<style scoped lang="scss"></style>
